#include "widget.h"
#include "ui_widget.h"
#include <QVBoxLayout>
#include <QSurfaceFormat>
#include <vtkSmartPointer.h>
#include <vtkParametricFunctionSource.h>
#include <vtkParametricSpline.h>
#include <vtkCellArray.h>
#include <vtkDoubleArray.h>
#include <vtkCellData.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkGlyph3DMapper.h>
#include <vtkSphereSource.h>
#include <vtkNamedColors.h>
#include <vtkAutoInit.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <QVTKOpenGLWidget.h>
#include <vtkAxesActor.h>
#include "tools/CUtil.h"
#include <QDebug>
#include "fVoxelsAnalysis.h"
#include <vtkOrientationMarkerWidget.h>
#include "tools/CPropPicker.h"
#include "tools/CImport.h"
#include "tools/CAnalysisNormals.h"
#include <QKeyEvent>
#include "CTestUtil.h"
#include <vtkSTLWriter.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    _analysis=0;
    CUtil::Instance()->registor();
    connect(CUtil::Instance(),SIGNAL(sLog(QString)),this,SLOT(onLog(QString)));
    initVtkWindow();
    connect(ui->pushButtonVoxelsAnalysis,SIGNAL(clicked(bool)),this,SLOT(onAnalysis()));
    connect(ui->pushButtonOpen,SIGNAL(clicked(bool)),this,SLOT(onOpen()));
//    test();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::updateVtk()
{
    _widget->GetRenderWindow()->Render();
}

void Widget::onOpen()
{
    vtkSmartPointer<vtkPolyData> data=CImport().import();
    if(!data)return;
#if 1
    vtkSmartPointer<vtkPolyDataMapper> mapper=
            vtkPolyDataMapper::New();
    mapper->SetInputData(data);
    _models.append(data);
    vtkSmartPointer<vtkActor> actor=vtkActor::New();
    actor->SetMapper(mapper);
    _renderer->AddActor(actor);
#else
    CTestUtil util;
    util.polyData=data;
    util.test();
//    vtkSmartPointer<vtkActor> actor=vtkActor::New();
//    actor->SetMapper(util.polyMapper);
//    _renderer->AddActor(actor);
    vtkSmartPointer<vtkSTLWriter> writer=vtkSTLWriter::New();
    writer->SetFileName("./test.stl");
    writer->SetFileTypeToBinary();
    writer->SetInputData(util.polyMapper->GetInput());
    writer->Write();
#endif
    updateVtk();
}

void Widget::onAnalysis()
{
    qDebug()<<"show analysis dialog.";
    if(!_analysis)
    {
        _analysis=new fVoxelsAnalysis(this);
        _analysis->setWindowFlag(Qt::Dialog);
    }
    _analysis->show();

}

void Widget::onLog(const QString &msg)
{
    ui->plainTextEdit->appendPlainText(msg);
}

void Widget::onColculateNormals()
{
    CAnalysisNormals an;
    an.setData(_models[0]);
    vtkSmartPointer<vtkMapper>mapper= an.getOutputData();
    vtkSmartPointer<vtkActor> actor=vtkActor::New();
    actor->SetMapper(mapper);
    actor->GetProperty()->SetColor(0,0.7,0.3);
    _renderer->AddActor(actor);
    updateVtk();

}

void Widget::keyPressEvent(QKeyEvent *e)
{
    switch (e->key()) {
    case Qt::Key_N:
        if(e->modifiers()&Qt::ControlModifier)
            onColculateNormals();
        break;
    default:
        break;
    }
}

void Widget::mousePressEvent(QMouseEvent *e)
{
}

void Widget::initVtkWindow()
{
    qDebug()<<"Vtk window initialize...";
    _widget=new QVTKOpenGLWidget;
    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow=vtkGenericOpenGLRenderWindow::New();
    QSurfaceFormat sf;
    sf.setSamples(8);
    _widget->setFormat(sf);
    _widget->SetRenderWindow(renderWindow);
    QVBoxLayout*layout=new QVBoxLayout;
    layout->addWidget(_widget);
    layout->setMargin(0);
    ui->widgetCenter->setLayout(layout);
    _renderer=vtkRenderer::New();
    _renderer->SetBackground(.1,.2,.3);
    //    _renderer->SetViewport(0,0,.5,1);
    vtkSmartPointer<vtkRenderWindowInteractor> interactor=vtkRenderWindowInteractor::New();
    renderWindow->SetInteractor(interactor);

    vtkSmartPointer<CPropPickerInteractorStyle> istyle=CPropPickerInteractorStyle::New();
    istyle->SetDefaultRenderer(_renderer);
    interactor->SetInteractorStyle(istyle);

    ///
    /// add axes at coner
    ///
    vtkSmartPointer<vtkAxesActor> axes=vtkAxesActor::New();
    vtkSmartPointer<vtkOrientationMarkerWidget> widget=vtkOrientationMarkerWidget::New();
    widget->SetOutlineColor(.93,.57,.12);
    widget->SetOrientationMarker(axes);
    widget->SetViewport(0,0,.2,.2);
    widget->SetInteractor(interactor);
//    widget->InteractiveOn();
    widget->SetEnabled(1);

    renderWindow->AddRenderer(_renderer);
    qDebug()<<"Vtk window created.";
}

void Widget::test()
{
    vtkSmartPointer<vtkNamedColors> colors=
            vtkSmartPointer<vtkNamedColors>::New();
    //create three points ,we will join (origin and p0) with a red line and (origin and p1) with a green line

    double origin[3]={0.f,0.f,0.f};
    double p0[3]={1.f,0.f,0.f};
    double p1[3]={0.0,1.0,0.f};
    double p2[3]={0.f,1.f,2.f};
    double p3[3]={1.f,2.f,3.f};

    vtkSmartPointer<vtkPoints> points=vtkSmartPointer<vtkPoints>::New();
    points->InsertNextPoint(origin);
    points->InsertNextPoint(p0);
    points->InsertNextPoint(p1);
    points->InsertNextPoint(p2);
    points->InsertNextPoint(p3);


    vtkSmartPointer<vtkParametricSpline> spline=
            vtkSmartPointer<vtkParametricSpline>::New();
    spline->SetPoints(points);

    vtkSmartPointer<vtkParametricFunctionSource> functionSource=
            vtkSmartPointer<vtkParametricFunctionSource>::New();

    functionSource->SetParametricFunction(spline);
    functionSource->Update();

    vtkSmartPointer<vtkSphereSource> sphere=
            vtkSmartPointer<vtkSphereSource>::New();
    sphere->SetPhiResolution(21);
    sphere->SetThetaResolution(21);
    sphere->SetRadius(0.1f);

    vtkSmartPointer<vtkPolyDataMapper> mapper=
            vtkSmartPointer<vtkPolyDataMapper>::New();

    mapper->SetInputConnection(functionSource->GetOutputPort());

    vtkSmartPointer<vtkActor> actor=
            vtkSmartPointer<vtkActor>::New();

    actor->SetMapper(mapper);
    double actorColor[]={0,1,0.2,0.3};
    actor->GetProperty()->SetColor(actorColor);
    actor->GetProperty()->SetLineWidth(3.0);

    vtkSmartPointer<vtkPolyData> polyData=
            vtkSmartPointer<vtkPolyData>::New();
    polyData->SetPoints(points);

    vtkSmartPointer<vtkGlyph3DMapper> pointMapper=
            vtkSmartPointer<vtkGlyph3DMapper>::New();
    pointMapper->SetInputData(polyData);
    pointMapper->SetSourceConnection(sphere->GetOutputPort());

    vtkSmartPointer<vtkActor> pointActor=
            vtkSmartPointer<vtkActor>::New();
    pointActor->SetMapper(pointMapper);
    double pointActorColor[]={0,5,0.2,0.3};
    pointActor->GetProperty()->SetColor(pointActorColor);
    _renderer->AddActor(pointActor);
}


